/*lic*/
#ifndef __EXPANSION_PORT_MODULE_H__
#define __EXPANSION_PORT_MODULE_H__

#include "main.h"
#include "I2CInitHelper.h"

// 端口组
#define IO_PORT_GROUP_1 0x01 // 0x01-0x0F
#define OUT_PORT_GROUP_1 0x10 // 0x10-0xF0

// 端口号
#define STATU_IO_0 0x00000001
#define STATU_IO_1 0x00000002
#define STATU_IO_2 0x00000004
#define STATU_IO_3 0x00000008
#define STATU_IO_4 0x00000010
#define STATU_IO_5 0x00000020
#define STATU_IO_6 0x00000040
#define STATU_IO_7 0x00000080
#define STATU_OUT_0 0x00000001
#define STATU_OUT_1 0x00000002
#define STATU_OUT_2 0x00000004
#define STATU_OUT_3 0x00000008
#define STATU_OUT_4 0x00000010
#define STATU_OUT_5 0x00000020
#define STATU_OUT_6 0x00000040
#define STATU_OUT_7 0x00000080
#define STATU_OUT_8 0x00000100
#define STATU_OUT_9 0x00000200
#define STATU_OUT_10 0x00000400
#define STATU_OUT_11 0x00000800
#define STATU_OUT_12 0x00001000
#define STATU_OUT_13 0x00002000
#define STATU_OUT_14 0x00004000

// 芯片初始化状态
#define CHIP_INIT 0x01

#define IO_OE 0x01 // 三台输出。如果为1，则IO口也允许输出，否则IO口仅可输入
#define DEC_L 0x02 // 扫描输出OC0-0C7。用于显示译码。用作拓展端口时应该0,即采用直接输出模式
#define DEC_H 0x04 // 扫描输出OC8-OC15
#define X_INT 0x08 // OC15作为输入中断通知引脚
#define OD_EN 0x10 // 切换开漏输出。大部分应该为0。
// 高位2、3是亮度控制。00b为全亮度。01b是四分之一。10b是二分之一。11b是全亮度但是禁止内部限流，禁止内部限流后一定要串接电阻，内部电阻为0
#define SLEEP 0x80 // 休眠 

typedef struct __Tag_Expansion_Port_Ctrl_Def {
	char name[32];
	// 设备资源锁
	struct rt_mutex device_lock;
	
	uint32_t io_port_status;
	uint32_t out_port_status;
	uint32_t shadow_io_port_status; // 影子寄存器，用来扫描和同步中断。用户仅仅应该能够操作影子寄存器
	uint32_t shadow_out_port_status; // 影子寄存器，用来扫描和同步中断
	
	uint32_t intc_io_oirt_regs; // 中断捕获记录
	uint8_t expansion_port_chip_status; // 初始化状态
	struct rt_event io_group_1_intc_envet; // io口中断事件
	void* io_group_1_event_params[32]; // IO端口组1通知参数

	
	// i2c控制对象
	I2c_Data_Task_Def i2c_ctrl_obj;
	// 芯片寄存器状态
	uint8_t chip_reg;
	
	rt_err_t (*Write_Port_Sataus)(struct __Tag_Expansion_Port_Ctrl_Def* obj, uint8_t port_group, uint32_t port, bool pin_status);
	rt_err_t (*Wait_For_Port_Intc)(struct __Tag_Expansion_Port_Ctrl_Def* obj, uint8_t port_group, uint32_t port, void* params);
	rt_err_t (*Read_Status_Reg)(struct __Tag_Expansion_Port_Ctrl_Def* obj);
	rt_err_t (*Write_Status_Reg)(struct __Tag_Expansion_Port_Ctrl_Def* obj);
}Expansion_Port_Ctrl_Def;

extern Expansion_Port_Ctrl_Def ch423s_port_ctrl_obj;
// 端口状态,用于参数传递。高4位是边沿状态，0是下降沿，其余为上升沿。低四位是电平状态。0是低电平，其余高电平
extern uint8_t port_status[32];

// 负责扩展芯片状态的读取和写入。所有监听任务的优先级都应该高于这个线程，且不应该在接收时清空状态位。本线程优先级为27
void Expansion_Flash_Thread(void *parmameter);

// 扩展中断
void INT_SRC_Expansion_Port_I2C_RXI_IrqCallback(void);
void INT_SRC_Expansion_Port_I2C_TXI_IrqCallback(void);
void INT_SRC_Expansion_Port_I2C_TEI_IrqCallback(void);
void INT_SRC_Expansion_Port_I2C_EEI_IrqCallback(void);

// 写入状态
rt_err_t Write_Port_Sataus_Interface(Expansion_Port_Ctrl_Def* obj, uint8_t port_group, uint32_t port, bool pin_status);
rt_err_t Wait_For_Port_Intc_Interface(Expansion_Port_Ctrl_Def* obj, uint8_t port_group, uint32_t port, void* params);
// 读取状态字
rt_err_t Read_Status_Reg_Interface(Expansion_Port_Ctrl_Def* obj);
// 写入状态字
rt_err_t Write_Status_Reg_Interface(Expansion_Port_Ctrl_Def* obj);

void Init_Expansion_Port(Expansion_Port_Ctrl_Def* obj, CM_I2C_TypeDef *CM_I2Cx, char* name);

#endif /* __EXPANSION_PORT_MODULE_H__ */

/*eof*/